// Copyright DustedPixels.com 2008. All rights reserved.

package com.dustedpixels.asm;

import junit.framework.TestCase;

import org.easymock.Capture;
import org.easymock.EasyMock;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.MethodNode;

import com.dustedpixels.asm.utils.MethodInliner;

/**
 * @author micapolos@gmail.com (Michal Pociecha-Los)
 */
public class MethodInlinerTest extends TestCase {

  private MethodVisitor methodInliner;
  private MethodNode inlinedMethod;
  private MethodVisitor expectedOut;

  @Override
  protected void setUp() {
    inlinedMethod = new MethodNode(0, "add", "(II)I", null, new String[0]);
    inlinedMethod.visitCode();
    inlinedMethod.visitVarInsn(Opcodes.ILOAD, 1);
    inlinedMethod.visitVarInsn(Opcodes.ILOAD, 2);
    inlinedMethod.visitInsn(Opcodes.IADD);
    inlinedMethod.visitInsn(Opcodes.IRETURN);
    inlinedMethod.visitMaxs(2, 3);
    inlinedMethod.visitEnd();
    
    expectedOut = EasyMock.createStrictMock(MethodVisitor.class);
    methodInliner = MethodInliner.inline(expectedOut, inlinedMethod, "Subtractor", "(II)I");
  }
  
  public void test() throws Exception {
    Capture<Label> l1 = new Capture<Label>();
    Capture<Label> l2 = new Capture<Label>();
    
    // Prepare expectations
    expectedOut.visitCode();
    expectedOut.visitVarInsn(Opcodes.ALOAD, 0);
    expectedOut.visitVarInsn(Opcodes.ILOAD, 1);
    expectedOut.visitVarInsn(Opcodes.ILOAD, 2);
    expectedOut.visitInsn(Opcodes.INEG);

    
    expectedOut.visitVarInsn(Opcodes.ISTORE, 5);
    expectedOut.visitVarInsn(Opcodes.ISTORE, 4);
    expectedOut.visitVarInsn(Opcodes.ASTORE, 3);
    
    expectedOut.visitVarInsn(Opcodes.ILOAD, 4);
    expectedOut.visitVarInsn(Opcodes.ILOAD, 5);
    expectedOut.visitInsn(Opcodes.IADD);
    
    expectedOut.visitJumpInsn(EasyMock.eq(Opcodes.GOTO), EasyMock.capture(l1));
    expectedOut.visitLabel(EasyMock.capture(l2));
    
    expectedOut.visitInsn(Opcodes.IRETURN);
    expectedOut.visitMaxs(5, 6);
    expectedOut.visitEnd();
    
    EasyMock.replay(expectedOut);
    
    methodInliner.visitCode();
    methodInliner.visitVarInsn(Opcodes.ALOAD, 0);
    methodInliner.visitVarInsn(Opcodes.ILOAD, 1);
    methodInliner.visitVarInsn(Opcodes.ILOAD, 2);
    methodInliner.visitInsn(Opcodes.INEG);
    methodInliner.visitMethodInsn(Opcodes.INVOKEINTERFACE, "Subtractor", "add", "(II)I");
    methodInliner.visitInsn(Opcodes.IRETURN);
    methodInliner.visitMaxs(3, 3);
    methodInliner.visitEnd();

    EasyMock.verify(expectedOut);
    
    assertEquals(l2.getValue(), l1.getValue());
  }
}
